/**
 * 存储工具类
 * 提供安全的本地存储操作和数据管理功能
 * 基于 AsyncStorage 封装，增加错误处理和数据验证
 * 
 * 作者：AI语言学习应用开发团队
 * 创建时间：2024年
 * 更新时间：2024年
 * 
 * 主要功能：
 * - 安全的数据存储和读取操作
 * - 数据完整性校验和版本兼容性检查
 * - 批量操作和数据统计功能
 * - 数据备份和恢复机制
 * - 存储空间管理和清理功能
 */
import AsyncStorage from '@react-native-async-storage/async-storage';
import { ValidationUtils, ObjectUtils, ErrorUtils } from './CommonUtils';

/**
 * 存储工具类
 * 提供统一的存储接口和数据安全保障
 */
export class StorageUtils {
  // 存储键名前缀，用于避免键名冲突
  static KEY_PREFIX = 'duolingo_app_';
  
  // 数据版本号，用于数据迁移
  static DATA_VERSION = '1.0.0';

  /**
   * 安全存储数据
   * @param {string} key - 存储键名
   * @param {any} value - 要存储的数据
   * @param {boolean} addPrefix - 是否添加键名前缀
   * @returns {Promise<boolean>} 存储是否成功
   */
  static async setItem(key, value, addPrefix = true) {
    try {
      // 验证参数
      if (!key || typeof key !== 'string') {
        throw new Error('存储键名必须是非空字符串');
      }

      const finalKey = addPrefix ? `${this.KEY_PREFIX}${key}` : key;
      
      // 创建存储数据结构
      const dataToStore = {
        value,
        version: this.DATA_VERSION,
        timestamp: new Date().toISOString(),
        checksum: this.generateChecksum(value)
      };

      await AsyncStorage.setItem(finalKey, JSON.stringify(dataToStore));
      return true;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.setItem', error, { key, valueType: typeof value });
      return false;
    }
  }

  /**
   * 安全读取数据
   * @param {string} key - 存储键名
   * @param {any} defaultValue - 默认值
   * @param {boolean} addPrefix - 是否添加键名前缀
   * @returns {Promise<any>} 读取的数据或默认值
   */
  static async getItem(key, defaultValue = null, addPrefix = true) {
    try {
      // 验证参数
      if (!key || typeof key !== 'string') {
        throw new Error('存储键名必须是非空字符串');
      }

      const finalKey = addPrefix ? `${this.KEY_PREFIX}${key}` : key;
      const storedData = await AsyncStorage.getItem(finalKey);
      
      if (!storedData) {
        return defaultValue;
      }

      const parsedData = JSON.parse(storedData);
      
      // 检查数据完整性
      if (!this.validateStoredData(parsedData)) {
        ErrorUtils.logWarning('StorageUtils.getItem', '存储数据验证失败', { key });
        return defaultValue;
      }

      // 检查数据版本兼容性
      if (!this.isVersionCompatible(parsedData.version)) {
        ErrorUtils.logWarning('StorageUtils.getItem', '存储数据版本不兼容', { 
          key, 
          storedVersion: parsedData.version, 
          currentVersion: this.DATA_VERSION 
        });
        // 可以在这里实现数据迁移逻辑
      }

      return parsedData.value;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.getItem', error, { key });
      return defaultValue;
    }
  }

  /**
   * 删除存储数据
   * @param {string} key - 存储键名
   * @param {boolean} addPrefix - 是否添加键名前缀
   * @returns {Promise<boolean>} 删除是否成功
   */
  static async removeItem(key, addPrefix = true) {
    try {
      if (!key || typeof key !== 'string') {
        throw new Error('存储键名必须是非空字符串');
      }

      const finalKey = addPrefix ? `${this.KEY_PREFIX}${key}` : key;
      await AsyncStorage.removeItem(finalKey);
      return true;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.removeItem', error, { key });
      return false;
    }
  }

  /**
   * 检查键是否存在
   * @param {string} key - 存储键名
   * @param {boolean} addPrefix - 是否添加键名前缀
   * @returns {Promise<boolean>} 键是否存在
   */
  static async hasKey(key, addPrefix = true) {
    try {
      const finalKey = addPrefix ? `${this.KEY_PREFIX}${key}` : key;
      const value = await AsyncStorage.getItem(finalKey);
      return value !== null;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.hasKey', error, { key });
      return false;
    }
  }

  /**
   * 获取所有应用相关的存储键
   * @returns {Promise<Array<string>>} 键名数组
   */
  static async getAllKeys() {
    try {
      const allKeys = await AsyncStorage.getAllKeys();
      return allKeys.filter(key => key.startsWith(this.KEY_PREFIX));
    } catch (error) {
      ErrorUtils.logError('StorageUtils.getAllKeys', error);
      return [];
    }
  }

  /**
   * 清除所有应用相关的存储数据
   * @returns {Promise<boolean>} 清除是否成功
   */
  static async clearAppData() {
    try {
      const appKeys = await this.getAllKeys();
      if (appKeys.length > 0) {
        await AsyncStorage.multiRemove(appKeys);
      }
      return true;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.clearAppData', error);
      return false;
    }
  }

  /**
   * 批量设置数据
   * @param {Array<Array>} keyValuePairs - 键值对数组 [[key, value], [key, value]]
   * @param {boolean} addPrefix - 是否添加键名前缀
   * @returns {Promise<boolean>} 设置是否成功
   */
  static async multiSet(keyValuePairs, addPrefix = true) {
    try {
      if (!Array.isArray(keyValuePairs)) {
        throw new Error('键值对必须是数组格式');
      }

      const processedPairs = keyValuePairs.map(([key, value]) => {
        const finalKey = addPrefix ? `${this.KEY_PREFIX}${key}` : key;
        const dataToStore = {
          value,
          version: this.DATA_VERSION,
          timestamp: new Date().toISOString(),
          checksum: this.generateChecksum(value)
        };
        return [finalKey, JSON.stringify(dataToStore)];
      });

      await AsyncStorage.multiSet(processedPairs);
      return true;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.multiSet', error, { pairsCount: keyValuePairs.length });
      return false;
    }
  }

  /**
   * 批量获取数据
   * @param {Array<string>} keys - 键名数组
   * @param {boolean} addPrefix - 是否添加键名前缀
   * @returns {Promise<Object>} 键值对象
   */
  static async multiGet(keys, addPrefix = true) {
    try {
      if (!Array.isArray(keys)) {
        throw new Error('键名必须是数组格式');
      }

      const finalKeys = keys.map(key => addPrefix ? `${this.KEY_PREFIX}${key}` : key);
      const results = await AsyncStorage.multiGet(finalKeys);
      
      const resultObject = {};
      results.forEach(([key, value], index) => {
        const originalKey = keys[index];
        if (value) {
          try {
            const parsedData = JSON.parse(value);
            if (this.validateStoredData(parsedData)) {
              resultObject[originalKey] = parsedData.value;
            } else {
              resultObject[originalKey] = null;
            }
          } catch (parseError) {
            ErrorUtils.logError('StorageUtils.multiGet.parse', parseError, { key: originalKey });
            resultObject[originalKey] = null;
          }
        } else {
          resultObject[originalKey] = null;
        }
      });

      return resultObject;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.multiGet', error, { keysCount: keys.length });
      return {};
    }
  }

  /**
   * 生成数据校验和
   * @param {any} data - 数据
   * @returns {string} 校验和
   */
  static generateChecksum(data) {
    try {
      const str = JSON.stringify(data);
      let hash = 0;
      for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i);
        hash = ((hash << 5) - hash) + char;
        hash = hash & hash; // 转换为32位整数
      }
      return hash.toString(36);
    } catch (error) {
      return '';
    }
  }

  /**
   * 验证存储数据的完整性
   * @param {Object} storedData - 存储的数据对象
   * @returns {boolean} 数据是否有效
   */
  static validateStoredData(storedData) {
    if (!storedData || typeof storedData !== 'object') {
      return false;
    }

    // 检查必需字段
    const requiredFields = ['value', 'version', 'timestamp'];
    for (const field of requiredFields) {
      if (!(field in storedData)) {
        return false;
      }
    }

    // 验证校验和（如果存在）
    if (storedData.checksum) {
      const expectedChecksum = this.generateChecksum(storedData.value);
      if (storedData.checksum !== expectedChecksum) {
        return false;
      }
    }

    return true;
  }

  /**
   * 检查版本兼容性
   * @param {string} storedVersion - 存储的版本号
   * @returns {boolean} 版本是否兼容
   */
  static isVersionCompatible(storedVersion) {
    if (!storedVersion) return false;
    
    // 简单的版本比较，可以根据需要扩展
    const [storedMajor] = storedVersion.split('.');
    const [currentMajor] = this.DATA_VERSION.split('.');
    
    return storedMajor === currentMajor;
  }

  /**
   * 获取存储使用情况统计
   * @returns {Promise<Object>} 存储统计信息
   */
  static async getStorageStats() {
    try {
      const appKeys = await this.getAllKeys();
      let totalSize = 0;
      const keyStats = [];

      for (const key of appKeys) {
        try {
          const value = await AsyncStorage.getItem(key);
          const size = value ? value.length : 0;
          totalSize += size;
          keyStats.push({
            key: key.replace(this.KEY_PREFIX, ''),
            size,
            sizeFormatted: this.formatBytes(size)
          });
        } catch (error) {
          // 忽略单个键的错误
        }
      }

      return {
        totalKeys: appKeys.length,
        totalSize,
        totalSizeFormatted: this.formatBytes(totalSize),
        keyStats: keyStats.sort((a, b) => b.size - a.size)
      };
    } catch (error) {
      ErrorUtils.logError('StorageUtils.getStorageStats', error);
      return {
        totalKeys: 0,
        totalSize: 0,
        totalSizeFormatted: '0 B',
        keyStats: []
      };
    }
  }

  /**
   * 格式化字节大小
   * @param {number} bytes - 字节数
   * @returns {string} 格式化后的大小字符串
   */
  static formatBytes(bytes) {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  }

  /**
   * 备份存储数据
   * @returns {Promise<Object|null>} 备份数据或null
   */
  static async backupData() {
    try {
      const appKeys = await this.getAllKeys();
      const backup = {
        version: this.DATA_VERSION,
        timestamp: new Date().toISOString(),
        data: {}
      };

      for (const key of appKeys) {
        try {
          const value = await AsyncStorage.getItem(key);
          if (value) {
            backup.data[key] = value;
          }
        } catch (error) {
          // 记录但不阻止备份过程
          ErrorUtils.logWarning('StorageUtils.backupData', `备份键 ${key} 失败`, { error: error.message });
        }
      }

      return backup;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.backupData', error);
      return null;
    }
  }

  /**
   * 从备份恢复数据
   * @param {Object} backupData - 备份数据
   * @returns {Promise<boolean>} 恢复是否成功
   */
  static async restoreData(backupData) {
    try {
      if (!backupData || typeof backupData !== 'object' || !backupData.data) {
        throw new Error('无效的备份数据格式');
      }

      // 检查版本兼容性
      if (!this.isVersionCompatible(backupData.version)) {
        ErrorUtils.logWarning('StorageUtils.restoreData', '备份数据版本不兼容', {
          backupVersion: backupData.version,
          currentVersion: this.DATA_VERSION
        });
      }

      // 清除现有数据
      await this.clearAppData();

      // 恢复备份数据
      const keyValuePairs = Object.entries(backupData.data);
      await AsyncStorage.multiSet(keyValuePairs);

      return true;
    } catch (error) {
      ErrorUtils.logError('StorageUtils.restoreData', error);
      return false;
    }
  }
}